package cn.itcast.mq.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.retry.MessageRecoverer;
import org.springframework.amqp.rabbit.retry.RepublishMessageRecoverer;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@Slf4j
public class CommonConfig implements  ApplicationContextAware{
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);

        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                String id = correlationData.getId();
                if (ack){
                log.info("消息确认回调触发 消息已经成功发送到交换机中 消息的id为{}" , id);
                    }else {
                    log.error("消息确认回调触发 消息发送失败 消息的id为{} ， 失败原因为{}" , id , cause);
                    }
            }
        });
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            @Override
            public void returnedMessage(Message message, int replyCode, String replyText,
                                        String exchange, String routingKey) {
                log.info("消息发送失败，应答码{}，原因{}，交换机{}，路由键{},消息{}",
                        replyCode, replyText, exchange, routingKey, message.toString());
            }
        });
    }

    //创建交换机

    @Bean
    DirectExchange simpleDirect(){
        return new DirectExchange("simple.direct" ,true , false);
    }

    @Bean
    Queue simpleQueue(){
        return  new Queue("simple.queue",true);
    }

    @Bean
    Binding bindingSimpleQueue(){
        return BindingBuilder.bind(simpleQueue()).to(simpleDirect()).with("simple");
    }

    @Bean
    DirectExchange errorExchange(){
        return new DirectExchange("error.direct");
    }

    @Bean
    Queue errorQueue(){
        return new Queue("error.queue");
    }

    @Bean
    Binding bindingErrorQueue(){
        return BindingBuilder.bind(errorQueue()).to(errorExchange()).with("error");
    }

    @Bean
    MessageRecoverer republicMessage(RabbitTemplate rabbitTemplate){
    return  new RepublishMessageRecoverer(rabbitTemplate,"error.direct","error");

    }

    // 声明死信交换机 dl.direct
    @Bean
    public DirectExchange dlExchange(){
        return new DirectExchange("dl.direct", true, false);
    }
    // 声明存储死信的队列 dl.queue
    @Bean
    public Queue dlQueue(){
        return new Queue("dl.queue", true);
    }
    // 将死信队列 与 死信交换机绑定
    @Bean
    public Binding dlBinding(){
        return BindingBuilder.bind(dlQueue()).to(dlExchange()).with("simple");
    }

    @Bean
    public Queue lazyQueue(){
        // 声明惰性队列
        return QueueBuilder.durable("lazy.queue").lazy().build();
    }

    @Bean
    public Queue normalQueue(){
        // 声明惰性队列
        return QueueBuilder.durable("normal.queue").build();
    }
}
